#ifndef __BoardTask_C
#define __BoardTask_C
#ifdef UsingFreeRTOS

#include "BoardTask.h"

TaskHandle_t xTaskProtcRecover;
TaskHandle_t xTaskMsgTreat;
TaskHandle_t xTaskLedBlink;
#ifdef LedCtrl_Rolling
TaskHandle_t xTaskLedRolling;
#endif

// 任务：设备启动
void vTaskStartUp(void *pvParameters){ 	 
	 while(1){
      #if beep_type > 0
			// 蜂鸣器任务
			if(system_time - led_startUp_TmRecode > startBeepTime){    
					// 蜂鸣器停止叫  
					stopBeep();  
			}
			#endif
      // 启动一段时间后，关闭灯			
			if(system_time - led_startUp_TmRecode > ledStartUpBlinkTime){
				  #ifdef Using_LedCtrl_74HC595
					Led595_start(0xff);			
				  #elif define Using_LedCtrl_MCUPin
					led_off(Led_All);
					#endif
			} 
      if(system_time - led_startUp_TmRecode > (ledStartUpHoldDarkTime + ledStartUpBlinkTime)){
			    system_started = 1; 
			    // 启动任务关闭;			    
				  vTaskDelete(NULL);
		  }			 
		  vTaskDelay (100);
	 }
}

// 任务：Led灯闪烁
void vTaskLedBlink(void *pvParameters){	  
	  while(1){
			  // printf("vTaskLedBlink %d \r\n",Led595_bits);
				// 亮灭控制数组; 0 = 亮；1 = 控制灭。
				uint16_t ledCtrlTm[2]  = {0,0};
				ledCtrlTm[0] = ledBlinkIntv[0] * ledBlinkDuty / 100;
				if(ledBlinkTms > 0 && iLed == ledBlinkTms - 1){
						ledCtrlTm[1] = ledBlinkIntv[1];			  
				}else{
						ledCtrlTm[1] = ledBlinkIntv[0] * (100 - ledBlinkDuty) / 100;	
				}
				// 开始亮灯
				if(Led_bits > 0){
						led_on(Led_bits);
				}						
				#ifdef Using_LedCtrl_74HC595
				if(Led595_bits != 0xff){
						Led595_start(Led595_bits);
				}							
				#endif	
				// 延时
				vTaskDelay(ledCtrlTm[0]); 
				// 开始灭灯
				if(Led_bits > 0){
					  if(LedOff_bits <= 0){
							  LedOff_bits = Led_bits;
						}
						led_off(LedOff_bits); 
				}
				#ifdef Using_LedCtrl_74HC595
				if(Led595_bits != 0xff){
						Led595_start(LedOff595_bits); 
				}
				#endif
				vTaskDelay(ledCtrlTm[1]); 
				// 指针自增
				iLed++;
				if(iLed == ledBlinkTms){ 
						iLed = 0;
				}
		}	  
}

#if Using_UART_LCD > 0
#if Using_UART_LCD == LCD_0P42_IIC
// 显示屏初始化任务
void vTaskOledInit(void *pvParameters){	  
	  while(1){
			  oled_reset_Pin_init();
				IIC_Pin_init();
				I2C_TX_DMA_Init();
				IIC_init();
				GPIO_ResetBit(OLed_Reset_PinPort,OLed_Reset_PinId);
				vTaskDelay(200);
				GPIO_SetBit(OLed_Reset_PinPort,OLed_Reset_PinId);
				vTaskDelay(10);
				oled_register_config();
				vTaskDelay(50);
			  oled_reset_step = 2;
			  // 任务关闭;			    
				vTaskDelete(NULL);
		}
}
#endif
// 显示屏刷新
void vTaskShowRefresh(void *pvParameters){	  
	  while(1){
			  #if Using_UART_LCD == LCD_0P42_IIC 
			  if(oled_reset_step > 1){
					  getShowData();
					  #ifdef SYS_DEBUG
	          //printf(" %d   %d   \r\n",OledRefresh,oled_reset_step);
	          #endif
				}		
			  vTaskDelay(refreshOledFreq * 10); 
			  #elif Using_UART_LCD == LCD_4P3_UART 
			  // 刷新屏幕数据						  
				display_write_variate(DATA_TEMPEARTURE,(uint16_t)(TMP_BoardIn * 10));  
//				display_write_variate(DATA_CHG_VOLTAGE,(uint16_t)(UI_Data.U_RMS));	 
//				display_write_variate(DATA_PRACTICAL_CURRENT,(uint16_t)(UI_Data.I_RMS * 10));	 
//				display_write_variate(DATA_RATED_CURRENT,(uint16_t)(I_State_Flag.I_rated_value));   
//				display_write_variate(DATA_ELECTRIC_QUANTITY,(uint16_t)(UI_Data.QOE * 100)); 
				// 倒计时显示
//				display_write_arr_variate(TMRTXT_COUNTDOWN,countdownStart,1); 
//				countdownStart[0]--;
//				if(countdownStart[0] < 0) countdownStart[0] = 0; 
				// 计时显示 
				// display_write_arr_variate(TMRTXT_TIMER_SHOW,timer_recoder,3); 
//				display_write_rtc(TMRTXT_TIMER_SHOW); 
//				tmrTimeAdd(timer_recoder,3); 		
			  vTaskDelay(refreshLCDDataFreq * 10); 
			  #endif
		}
}	
#endif

// 启动Led灯闪烁
void mTaskLedBlinkStart(){
	  vTaskResume(xTaskLedBlink);
}
// 结束Led闪烁
void mTaskLedBlinkStop(){
	  vTaskSuspend(xTaskLedBlink);
}

#ifdef LedCtrl_Rolling
// 任务：Led滚动
void vTaskLedRolling(void *pvParameters){	  
	  while(1){
			  #ifdef Led7Pin_ABCDEFG
				if(iLed == 3){
						Led595_bits = 0xE2;
				}else if(iLed == 4){
						Led595_bits = 0xC6;
				}else if(iLed == 5){
						Led595_bits = 0x8E;					  
				}else if(iLed == 6){
						Led595_bits = 0x1E;
						iLed = 0;
				}else{
						Led595_bits = Led595_bits << 1;
				}			
				#elif defined Led5Pin_ABCDE
				if(iLed == 3){
						Led595_bits = 0xC8;
				}else if(iLed == 4){
						Led595_bits = 0x98;
				}else if(iLed == 5){
						Led595_bits = 0x38;
						iLed = 0;
				}else{
						Led595_bits = Led595_bits << 1;
				}
				#endif
				Led595_start(Led595_bits);
				iLed++;
				vTaskDelay(mTask_ledRoll_bit * 10);				
		}
}

// 启动Led灯滚动
void mTaskLedRollStart(){
	  vTaskResume(xTaskLedBlink);
}

// 结束Led滚动
void mTaskLedRollStop(){
	  vTaskSuspend(xTaskLedRolling);
}
#endif

// 所有灯都处于关闭状态
void mTaskLedAllBlinkStop(){
    // 关闭所有的闪灯任务：
	  vTaskSuspend(xTaskLedBlink);
	  #ifdef LedCtrl_Rolling
	  // 关闭滚动
	  vTaskSuspend(xTaskLedRolling);
	  // 所有灯关闭
	  Led595_start(0xff);
	  led_off(BL_PinId);
	  #elif CHGR_panel_Sel == CHGR_panel_B26
	  // 关闭所有灯;
	  led_off(Led_All);
	  #endif
}

// 灯显示策略任务：
void vTaskLedShow(void *pvParameters){    
	  while(1){			  
			  //mTaskMain_strategy();
			  vTaskDelay(mTaskMainFreq * 10);
		}
}

#if (defined RCD_TYPE_B) && (testSelfLeak > 0)
// 任务：设备漏电自检
void vTaskLeakSelfTest(void *pvParameters){	 
	 while(1){
		  #if testSelfLeak == Leak_RCPD_08BS75_2P2
		  // 延时1：
		  vTaskDelay(leak_step1_tm);
		  leak_test_set_high();
		  // 延时2：
		  vTaskDelay(leak_step3_tm - leak_step1_tm);
      leak_test_set_low();
		  leak_test_init_step = 4;
		  vTaskDelay(leak_step4_tm - leak_step1_tm);
		  // 初始化完成：
		  leak_test_init_step = 5;
		  leakage_occ_recode = 0;
		  #elif testSelfLeak == Leak_FM2161A
      vTaskDelay(Leak_step_t1);		  
		  leak_FMCHK_set_low();
		  leak_test_init_step = 2;
		  vTaskDelay(Leak_step_t2);
		  leak_FMCHK_set_high();
		  leak_test_init_step = 3;
		  vTaskDelay(Leak_step_t3);
		  leak_test_set_low();
			leak_test_init_step = 4;
			vTaskDelay(Leak_step_t4);
		  leak_test_set_high();
			leak_test_init_step = 5;
		  vTaskDelay(leak_stepLast_tm - Leak_step_t1 - Leak_step_t2 - Leak_step_t3 - Leak_step_t4);
			leak_test_init_step = 6;
		  #endif
      // 退出任务：
		  vTaskDelete(NULL);
	 }
}  
#endif

// 错误强行恢复，并充电
void vTaskProtcRecover(void *pvParameters){
	  while(1){
			  while(faultRecv_counts < faultRecv_Limit_tms && faultCode > 0){					  
					  // 等待恢复结束：
						vTaskDelay (fault_recvr_intv);	
						protect_recover_action();
						// 任务挂起
						vTaskSuspend(NULL);
						// 恢复检测延时
						vTaskDelay (check_state_ticks * 10);
				}
				// 任务延时
				vTaskDelay (check_state_ticks * 10);
		}
}

#if CarD1_Protect > 0 
// CarD1检测任务
void vTaskCarD1Detect(void *pvParameters){	  
	  while(1){
				if(cp_data.value_cope_id != CP_12 && CarD1Param.CarD1_TestStart > 0){
						while(CarD1_Level == 1){
							  
							  // 有分压就是坏的;记录在自检期间，检测到的次数。
								CarD1Param.CarD1_MarkNum++;
								if(CarD1Param.CarD1_MarkNum >= 150){ 
										// 车端二极管坏了
										if(cp_data.value_cope_id != CP_12){
												faultCode = carD1_bad;
												mTask_Fault = mTask_Fault | (0x0001 << (carD1_bad - 1));  //位置1	                
										}	
										CarD1Param.CarD1_TestStart = 0; //停止车载二极管自检
								}
							  
//							  CarD1_occ_times++;
//								if(CarD1_occ_times > 250) CarD1_occ_times = 250;
//								vTaskDelay(CarD1EintFreq * 10); // 50 * 500ms检测一次;							  
//								if(CarD1_occ_times * CarD1EintFreq * 10 > CarD1_Available_tm){
//										 union dataFormatTrans msgData;
//										 faultCode = carD1_bad;
//										 msgData.int16DataArr[0] = faultMsg;
//										 msgData.int16DataArr[1] = (uint16_t)faultCode;										 
//										 xTaskNotify(xTaskMsgTreat,msgData.uint32Data,eSetValueWithOverwrite);
//										 // CarD1低电平计数归0
//										 CarD1_occ_times = 0;
//								}

								
						}		
				}				
				// 延迟：500ms
				vTaskDelay (CarD1EintFreq * 10);
		}
}
#endif

// 蜂鸣器任务
void vTaskBeepRun(void *pvParameters){
	  while(1){
			  // 蜂鸣器鸣叫
				#if beep_type == beep_APM
				if(beep_step > 0 && beep_step < beep_times * 2){
						beep_step_run();
				}
				#endif
		
				// Lcd蜂鸣器鸣叫
				#if beep_type == beep_LCD && Using_UART_LCD == LCD_4P3_UART
				if(beep_step > 0 && beep_step <= beep_times){ 
					  lcd_beep((uint16_t)(beep_Tm / 10));
						beep_step++;
					  vTaskDelay (beep_Tm + beep_idle_Tm);					  
				} 
				#endif 
		}
}
/*
// 接地检测任务
void vTaskPEDetect(void *pvParameters){	  
	  while(1){
				PE_occ_times = 0;
			  // 统计PE=0的坚持时长; 越长就是没有接地。
			  while(PE_get_level() == 0){
					  PE_occ_times++;
					  if(PE_occ_times > 250) PE_occ_times = 250;
					  vTaskDelay (EintFreq * 10); // 50ms检测一次;
            if(PE_occ_times * EintFreq * 10 > PE_Available_tm){
					       // 没有接地;报错;							   
							   union dataFormatTrans msgData;
							   faultCode = PE_protection;
							   msgData.int16DataArr[0] = faultMsg;
							   msgData.int16DataArr[1] = (uint16_t)faultCode;								 
                 xTaskNotify(xTaskMsgTreat,msgData.uint32Data,eSetValueWithOverwrite);
							   // PE低电平计数归0
                 PE_occ_times = 0;
				    }					
				}
				// 延迟：50ms
				vTaskDelay (EintFreq * 10);
		}
}
*/
#ifdef Key1 
// 按键检测任务：
void vTaskKeyDetect(void *pvParameters){	  
	  while(1){
        // 按键检测
			  keyDetect();
		    // 延时：
		    vTaskDelay (100);
	 }
}
#endif

// 消息处理任务：
void vTaskMsgTreat(void *pvParameters){	  
	  union  dataFormatTrans notify_val;
	  BaseType_t xResult;	  
    while(1){
			  // 得到通知消息让通知值清0
			  xResult = xTaskNotifyWait(0, 0,&notify_val.uint32Data,portMAX_DELAY);
			  if(xResult == pdPASS){
					  if(notify_val.int16DataArr[0] == keyDownMsg){
							  //记录第一次接收到的按键的时间
							  mEventKeyTreat();							  
						}else if(notify_val.int16DataArr[0] == faultMsg){
							  uint8_t resumeType = mTaskFault_strategy();
							  if(resumeType == 1){
									  vTaskResume(xTaskProtcRecover);
								}							  
						}
				}
		    vTaskDelay(100);
		}	  
}

// 定时任务：
void vTaskTimerTicks(void *pvParameters){	  
	  while(1){
			  task_tms++;
			  
			  // IWDT_Refresh(); // 喂狗：
			
			  // 数据检测：100ms执行一次;
				if(task_tms % check_state_ticks == 0 && system_started > 0){
					  // 获取温度数据
					  getTMP_BoardIn();
			      getTMP_Ext1();
			      getTMP_Ext2();
						// 温度校对
						get_tmpr_state();
						// I校对
						get_I_state();
						// U校对						  
						get_U_state();
					  
					  // 处理错误
						if(mTask_Fault > 0){
								union dataFormatTrans msgData;
								msgData.int16DataArr[0] = faultMsg;
								msgData.int16DataArr[1] = (uint16_t)faultCode;
								xTaskNotify(xTaskMsgTreat,msgData.uint32Data,eSetValueWithOverwrite);
						}		
				}
				
			  // 电量保存频率
				#if GET_K_Actv != 0
				if(task_tms % QOE_save_ticks == 0 && cp_data.value_cope_id == CP_6){
						writeData[2].fltData = UI_Data.QOE;
						flash_write();
				}
				#endif	
				
			  vTaskDelay(10);
		}
}

#if (UI_Meter_Method == Meter_GuageIC)
// 从计量芯片中读取UI数据
void vTaskGetUIFromGuage(void *pvParameters){
	  while(1){
			  readUIValueFromGuage();		
			  // 2秒读一次;
			  vTaskDelay(read_UI_intv * 10);        
		}
}
#endif 

// 任务初始化并启动：
void taskInit(){
    #ifdef SYS_DEBUG
	  printf("   taskInit   \r\n");
	  #endif
	  // 设备启动
	  xTaskCreate(vTaskStartUp, "TpTask1", configMINIMAL_STACK_SIZE, NULL, 3,NULL);
	  
	  // 漏电启动
	  #if (defined RCD_TYPE_B) && (testSelfLeak > 0)
    xTaskCreate(vTaskLeakSelfTest, "TpTask2", configMINIMAL_STACK_SIZE + 32U, NULL, 3,NULL);
    #endif

    // OLED初始化并显示
	  #if Using_UART_LCD == LCD_0P42_IIC
    xTaskCreate(vTaskOledInit, "TpTask3", configMINIMAL_STACK_SIZE, NULL, 3,NULL);
    #endif	
	
	  // 闪灯
	  xTaskCreate(vTaskLedBlink, "LTTask1", configMINIMAL_STACK_SIZE, NULL, 3,&xTaskLedBlink);
	  vTaskSuspend(xTaskLedBlink);
	
	  // 滚动灯
		#ifdef LedCtrl_Rolling
	  xTaskCreate(vTaskLedRolling, "LTTask2", configMINIMAL_STACK_SIZE, NULL, 3,&xTaskLedRolling);
	  vTaskSuspend(xTaskLedRolling);
    #endif
		
		// OLED显示任务：刷新显示内容
		#if Using_UART_LCD == LCD_0P42_IIC
		xTaskCreate(vTaskShowRefresh, "LTTask13", configMINIMAL_STACK_SIZE, NULL, 3,NULL);
		#elif Using_UART_LCD == LCD_4P3_UART
    xTaskCreate(vTaskShowRefresh, "LTTask13", configMINIMAL_STACK_SIZE + 32U, NULL, 3,NULL);
		#endif
		  
	  // 灯显示策略任务：
	  xTaskCreate(vTaskLedShow, "LTTask4", configMINIMAL_STACK_SIZE, NULL, 3,NULL);	

    // 蜂鸣器播报
		xTaskCreate(vTaskBeepRun, "LTTask5", configMINIMAL_STACK_SIZE + 32U, NULL, 3,NULL);	
		
	  // 检测车载二极管任务
    #if CarD1_Protect > 0 		
	  xTaskCreate(vTaskCarD1Detect, "LTTask6", configMINIMAL_STACK_SIZE + 32U, NULL, 3,NULL);
	  #endif
		
	  // 检测接地任务
	  //xTaskCreate(vTaskPEDetect, "LTTask7", configMINIMAL_STACK_SIZE + 32U, NULL, 3,NULL);
		
	  // 检测按键任务
    xTaskCreate(vTaskKeyDetect, "LTTask8", configMINIMAL_STACK_SIZE + 32U, NULL, 4,NULL);
		
	  // 充电保护恢复任务：接地保护恢复，过压，过流保护恢复
	  xTaskCreate(vTaskProtcRecover, "LTTask9", configMINIMAL_STACK_SIZE + 32U, NULL, 3,&xTaskProtcRecover);
		vTaskSuspend(xTaskProtcRecover);
		
    // 消息处理任务
    xTaskCreate(vTaskMsgTreat, "LTTask10", configMINIMAL_STACK_SIZE, NULL, 4,&xTaskMsgTreat);
		
	  // 定时任务：定时获取电流电压等参数
    xTaskCreate(vTaskTimerTicks, "LTTask11", configMINIMAL_STACK_SIZE + 32U, NULL, 3,NULL);
		
		#if UI_Meter_Method == Meter_GuageIC
		// 读取计量芯片的数据
		xTaskCreate(vTaskGetUIFromGuage, "LTTask12", configMINIMAL_STACK_SIZE + 128U, NULL, 4,NULL);
		#endif
		
		
		
		// 任务调度启动
	  vTaskStartScheduler();		
}



#endif
#endif


